package pjn;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class GramaticalResolver {

    private Set<Integer> masculineVerb = new HashSet<Integer>(Arrays.asList(15, 16, 17, 30, 31, 32));
    private Set<Integer> feminineVerb = new HashSet<Integer>(Arrays.asList(18, 19, 20, 33, 34, 35));
    private Set<Integer> neuterVerb = new HashSet<Integer>(Arrays.asList(21, 22, 23, 36, 37, 38));
    private Set<Integer> pluralVerb = new HashSet<Integer>(Arrays.asList(24, 25, 26, 27, 28, 29, 39, 40, 41, 42, 43, 44));

    public GenderAndNumber resolveGenderAndNumber(String word, PartOfSpeech partOfSpeech) {
        int[] ids = JCLP.rec(word);
        if (ids.length > 0) {
            int[] numbers = JCLP.vec(ids[0], word);
            int number = numbers[0];

            if (partOfSpeech == PartOfSpeech.ADJECTIVE) {
                int k = (number - 1) / 7;
                switch (k) {
                case 0:
                    return GenderAndNumber.MASCULINE;
                case 2:
                    return GenderAndNumber.FEMININE;
                case 3:
                    return GenderAndNumber.NEUTER;
                case 4:
                case 5:
                    return GenderAndNumber.PLURAL;
                }
            } else if (partOfSpeech == PartOfSpeech.VERB) {
                if (masculineVerb.contains(number)) {
                    return GenderAndNumber.MASCULINE;
                } else if (feminineVerb.contains(number)) {
                    return GenderAndNumber.FEMININE;
                } else if (neuterVerb.contains(number)) {
                    return GenderAndNumber.NEUTER;
                } else if (pluralVerb.contains(number)) {
                    return GenderAndNumber.PLURAL;
                }
            } else if (partOfSpeech == PartOfSpeech.NOUN) {
                if (number > 7) {
                    return GenderAndNumber.PLURAL;
                }
                String label = JCLP.label(ids[0]);
                switch (label.charAt(1)) {
                case 'A':
                    return GenderAndNumber.MASCULINE;
                case 'D':
                    return GenderAndNumber.FEMININE;
                case 'E':
                    return GenderAndNumber.NEUTER;
                }
            }
        }

        return null;
    }

    public PartOfSpeech resolvePartOfSpeach(String word) {
        int[] ids = JCLP.rec(word);
        if (ids.length > 0) {
            int number = JCLP.pos(ids[0]);
            if (number == 1) {
                return PartOfSpeech.NOUN;
            } else if (number == 2) {
                return PartOfSpeech.VERB;
            } else if (number == 3) {
                return PartOfSpeech.ADJECTIVE;
            }
        }

        return null;
    }

    public boolean isItParticiple(String word) { //sprawdza czy czasownik to imieslow uprzedni
        PartOfSpeech partOfSpeech = resolvePartOfSpeach(word);
        int[] ids = JCLP.rec(word);
        if (ids.length > 0) {
            int[] numbers = JCLP.vec(ids[0], word);
            int number = numbers[0];

            if (partOfSpeech == PartOfSpeech.VERB && number == 47) {
                return true;
            }
        }

        return false;
    }

    public boolean isItGenitive(String word) { //sprawdza czy rzeczownik jest w dopelniaczu
        PartOfSpeech partOfSpeech = resolvePartOfSpeach(word);
        int[] ids = JCLP.rec(word);
        if (ids.length > 0) {
            int[] numbers = JCLP.vec(ids[0], word);
            int number = numbers[0];

            if (partOfSpeech == PartOfSpeech.NOUN && number == 2) {
                return true;
            }
        }

        return false;
    }

    public void resolveCharactersGendersAndNumbers(Set<Character> characters, List<String> sentences, Map<Integer, Set<Integer>> charactersInSentencesCount) {
        Splitter splitter = new Splitter();

        Set<Character> charactersToDelete = new HashSet<Character>();
        for (Character character : characters) {
            Map<GenderAndNumber, Integer> genderAndNumberCount = new HashMap<GenderAndNumber, Integer>();

            for (String name : character.getNames()) {
                for (Integer sentenceNumber : character.getNamesOccurenceSentences().get(name)) {
                    if (charactersInSentencesCount.get(1).contains(sentenceNumber)) {
                        int index = sentences.get(sentenceNumber).indexOf(name);

                        List<String> words = splitter.splitIntoWords(sentences.get(sentenceNumber).substring(0, index));
                        for (int i = words.size() - 1; i >= 0; i--) {
                            PartOfSpeech partOfSpeech = resolvePartOfSpeach(words.get(i));
                            if (partOfSpeech == null) {
                                continue;
                            } else if (partOfSpeech == PartOfSpeech.NOUN) {
                                break;
                            } else {
                                GenderAndNumber gan = resolveGenderAndNumber(words.get(i), partOfSpeech);
                                if (gan != null) {
                                    if (genderAndNumberCount.containsKey(gan)) {
                                        genderAndNumberCount.put(gan, genderAndNumberCount.get(gan) + 1);
                                    } else {
                                        genderAndNumberCount.put(gan, 1);
                                    }
                                }
                            }
                        }

                        words = splitter.splitIntoWords(sentences.get(sentenceNumber).substring(index + name.length()));
                        for (int i = 0; i < words.size(); i++) {
                            PartOfSpeech partOfSpeech = resolvePartOfSpeach(words.get(i));
                            if (partOfSpeech == null) {
                                continue;
                            } else if (partOfSpeech == PartOfSpeech.NOUN) {
                                break;
                            } else {
                                GenderAndNumber gan = resolveGenderAndNumber(words.get(i), partOfSpeech);
                                if (gan != null) {
                                    if (genderAndNumberCount.containsKey(gan)) {
                                        genderAndNumberCount.put(gan, genderAndNumberCount.get(gan) + 1);
                                    } else {
                                        genderAndNumberCount.put(gan, 1);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            int max = 0;
            GenderAndNumber winner = null;
            for (GenderAndNumber key : genderAndNumberCount.keySet()) {
                if (genderAndNumberCount.get(key) > max) {
                    max = genderAndNumberCount.get(key);
                    winner = key;
                }
            }
            if (winner == GenderAndNumber.PLURAL) {
                charactersToDelete.add(character);
            } else {
                character.setGender(winner);
            }
        }

        characters.removeAll(charactersToDelete);
    }

}
